home *** CD-ROM | disk | FTP | other *** search
/ MacTech 1 to 12 / MacTech-vol-1-12.toast / Source / MacTech® Magazine / Volume 10 - 1994 / 10.10 Oct 94 / Learning Smalltalk / WireListWindow.st < prev   
Encoding:
Text File  |  1994-09-13  |  20.2 KB  |  311 lines  |  [TEXT/QKSA]

  1.  
  2. DemoLib
  3.              name: #WireListWindow
  4.        superclass: Environment@#UIWindow
  5.             flags: 0x0
  6.          category: nil
  7. classInstanceVars: nil
  8. namedInstanceVars: #(info)
  9.     classPoolVars: nil
  10.             pools: nil
  11.        structures: nil
  12.       storageSize: 0
  13. !
  14. (DemoLib@#WireListWindow) metaclass description: (Text from: 'This is the UIWindow to support the WireListModel demo. It works together with WireList (a subclass if List), and WireListModel (a subclass of ApplicationModule).' styleRuns:((ScrapStyle basicNew: 0) storageSize: 22; storageFromHexString: '000100000000000C000A000100000009000000000000'))!
  15. DemoLib@#WireListWindow compileMethodSource: (
  16. Text from: 'createWindow
  17.  
  18.     | iconSpacing nextIconH topSection iconPen extent nextIconV |
  19.     
  20.    "Associate the window with its application module, label it, give it a min size
  21.     and defualt location, determine its bounds based on the main display device"
  22.      module := WireListModel new. 
  23.     
  24.     label := ''WireList''.
  25.     (positioner := WindowPositioner new) minHeight: 140; minWidth: 575. 
  26.  
  27.     extent := (GraphicDevice main contentBounds insetBy: 8) extent.
  28.     extent x: (extent x min: 624).
  29.     extent y: (extent y min: 428).
  30.     self bounds: ((0@0) extent: extent).
  31.  
  32.   "Next we set up window components, including BalloonHelp. Note the hierarchical structure.
  33.    Launch the WireListModel and use your mouse, together with the mouse position indicators
  34.    in the Console, to see how things are positioned. This window could have also been created
  35.    with the GUIBuilder"
  36.     
  37.     self
  38.         balloonHelp: 
  39.             (''WireListWIndow  Click in the main field to add points.  Drag points with mouse'',
  40.              '' down to reposition points. If you drag a point outside the black frame, you'',
  41.              '' can either click on its original location or add a new point inside the field.'');
  42.         addComponent: 
  43.         (   "Add a button"
  44.             (MUIButton new)
  45.                balloonHelp: (''Use this button to shorten the wire.'',
  46.                              '' It calls the #shorten method.'');
  47.                 positioner: (Positioner bounds: {2. 92+72+10.   17.  92+72+10+100 }     
  48.                                          scale: {0.  0.   0.  0});
  49.                      label: ‘shorten wire’;
  50.                         on: #buttonRelease send: #shorten to: self
  51.         );
  52.          addComponent: 
  53.         (   "Add another button"
  54.             (MUIButton new)
  55.                balloonHelp: (''Use this button to inspect the WireList'',
  56.                              '' definitions.'');
  57.                 positioner: (Positioner bounds: {2. 92+72+10+100 + 22.   17.  92+72+10+100+22+100  }     
  58.                                          scale: {0.  0.   0.  0});
  59.                      label: ‘inspect wire’;
  60.                         on: #buttonRelease send: #inspectWire to: self
  61.         );
  62.         addComponent: 
  63.         (   "Add a static text field for the wire length message. This is the 3rd component
  64.               and can be referenced as the 3rd object in the window''s list. e.g. self@3 "
  65.             (info := StaticTextField new)
  66.                balloonHelp: (''This field displays the updated'',
  67.                              '' wire length.'');
  68.                 positioner: (Positioner bounds: {2. 92+72+252.   17.  (extent x) - 2 }     
  69.                                          scale: {0.  0.   0.  0})
  70.         );
  71.         addComponent: 
  72.         (   "This is a TEField where you can enter messages to the WireListWindow"
  73.             (TEField new)
  74.                balloonHelp: (''Use this field to enter messages to your'',
  75.                              '' WireListWindow and press <return>.'',
  76.                              '' An example is [inspect]. Used for'',
  77.                              '' debugging and inspection.'');
  78.                   contents: ‘Enter message to self,<cr>’;  "<--- note use of styled text"
  79.                  frameType: nil;
  80.               penState: ((PenState new) textSize: 9; textFont: ''Geneva'');
  81.            scrollableWidth: 400;
  82.                 wordWrap: false;
  83.                 focusOrder: 1+self basicSize;    "Top Left Bottom Right"
  84.                 positioner: (Positioner bounds: {2. 4.   17.  92+72}     
  85.                                          scale: {0.  0.   0.  0});
  86.             on: #returnKey send: #commandTyped to: self
  87.         ).
  88.    
  89.    "This is what we do for a mouse button event in the main pane area; WireListWindow>>buttonDown
  90.     will determine the needed actions "    
  91.         
  92.  self on: #buttonPress send: #buttonDown to: self.' styleRuns:((ScrapStyle basicNew: 0) storageSize: 462; storageFromHexString: '001700000000000B000900040000000900000000000000000059000B0009000400000009999966660000000000F8000B00090004000000090000000000000000023A000B000900040000000999996666000000000366000B0009000400000009000000000000000004CB000B0009000400000009999966660000000004D9000B000900040000000900000000000000000634000C000900000000000900000000000000000640000B0009000400000009000000000000000006B5000B0009000400000009999966660000000006C9000B000900040000000900000000000000000827000C000900000000000900000000000000000833000B0009000400000009000000000000000008AB000B000900040000000999996666000000000954000B000900040000000900000000000000000ABA000B000900040000000999996666000000000B00000B000900040000000900000000000000000C55000B0009000400000009DD6B08C206A200000C59000B000900040000000900000000000000000C63000B0009000400000009DD6B08C206A200000C7F000B000900040000000900000000000000000E4E000B000900040000000999996666000000000ED4000B0009000400000009000000000000'))!
  93. (DemoLib@#WireListWindow methodAt: #'createWindow') protocolCategory: #'initialization'.!
  94. (DemoLib@#WireListWindow methodAt: #'createWindow') description: ('createWindow is called by the open message, UIWindow>>open. This open message is sent when the application is launched; see WIreListModel>>launch.').!
  95.  
  96. DemoLib@#WireListWindow compileMethodSource: (
  97. Text from: 'dimensionsChangedFrom: oldBounds to: newBounds
  98.  
  99.     | “Local (Method Scope) Variables Are Declared Here” |
  100.  
  101.    “This method is needed force updating of the graphic region on resizing. It is not normally 
  102.    required in cases where the graphic region is a GraphicPane”
  103.  
  104.     %% “Begin Compiler Directives”
  105.     %    
  106.     %   Method Author: ‘peskin’.
  107.     %   Method Created: ‘Thu 07/22/1993 12:58:14 PM’.
  108.     %
  109.     %   Private Method. “Use "Ensure Private Method" To Force Checking”
  110.     %   Method Protocol: nil.
  111.     %
  112.     %  Method Description: ''Special method for WireListModel demo; not normally needed. It is
  113.                             used to update a frame. Normally this will be taken care of in
  114.                             component updates (see DESolverWIndow example) ''.
  115.     %
  116.     %   Allow Undefined Identifiers: false.
  117.     %
  118.     %  “On Exception Do: [:exception | "Exception Handler Code Goes Here" ].”
  119.     %
  120.     %% “End Compiler Directives”
  121.     
  122.    super dimensionsChangedFrom: oldBounds to: newBounds.
  123.    self markAsDirty' styleRuns:((ScrapStyle basicNew: 0) storageSize: 1062; storageFromHexString: '003500000000000B000900040000000900000000000000000036000B000900040000000966663333000000000068000B00090004000000090000000000000000006F000B00090004000000096666333300000000010B000B000900040000000900000000000000000111000B000900040000000940004000400000000113000B000900040000000900000000000000000114000B000900040000000940004000400000000115000B00090004010000098000800080000000012E000B00090004000000094000400040000000012F000B000900040000000900000000000000000134000B000900040000000940004000400000000135000B00090004000000090000000000000000013E000B00090004000000094000400040000000013F000B000900040000000900000000000000000142000B00090004000000094000400040000000014F000B00090004000000090000000000000000015F000B000900040000000940004000400000000160000B000900040000000900000000000000000163000B000900040000000940004000400000000171000B000900040000000900000000000000000194000B0009000400000009400040004000000001E4000B0009000400000009000000000000000001E7000B0009000400000009400040004000000001F6000B000900040000000900000000000000000201000B000900040000000940004000400000000208000B00090004000000090000000000000000020A000B00090004000000094000400040000000021C000B000900040000000900000000000000000308000B000900040000000940004000400000000309000B00090004000000090000000000000000030E000B000900040000000940004000400000000315000B000900040000000900000000000000000318000B000900040000000940004000400000000333000B000900040000000900000000000000000335000B0009000400000009DD6B08C206A20000033A000B000900040000000900000000000000000340000B000900040000000940004000400000000347000B00090004000000090000000000000000034A000B000900040000000940004000400000000359000B00090004000000090000000000000000035D000B0009000400000009DD6B08C206A200000366000B000900040000000900000000000000000369000B00090004000000096666333300000000038B000B000900040000000900000000000000000394000B000900040000000940004000400000000395000B00090004000000090000000000000000039A000B00090004000000094000400040000000039E000B0009000401000009800080008000000003B5000B0009000400000009400040004000000003B6000B0009000400000009000000000000000003BF000B0009000400000009666633330000000003C5000B0009000400000009000000000000'))!
  124. (DemoLib@#WireListWindow methodAt: #'dimensionsChangedFrom:to:') protocolCategory: #'update'.!
  125. (DemoLib@#WireListWindow methodAt: #'dimensionsChangedFrom:to:') description: ('Special method for WireListModel demo; not normally needed. It is used to update a frame. Normally this will be taken care of in component updates (see DESolverWIndow example)').!
  126.  
  127. DemoLib@#WireListWindow compileMethodSource: (
  128. Text from: 'privateSelfRender: dirtyArea in: gPort color: isColor depth: pixelDepth
  129.  
  130.    "These first lines are boiler plate to avoid unnessessary redrawing of static component regions"
  131.     bg := ((self bounds copy) top: (bounds top + 20)) asRegion.
  132.     self componentsDo: [:component | bg := component removeBoundsFromBgArea: bg].
  133.     bg erase.
  134.  
  135.    
  136.     "Set the pen to blue, white background"
  137.     Color blue setForeground.
  138.     Color white setBackground.
  139.     (bounds copy) bottom: (bounds top + 19);erase.
  140.  
  141.    "Draw top blue line, three small vertical lines, bottom blue line"
  142.     p := bounds left @ (bounds top + 17).
  143.     gPort movePenTo: p; drawLineByH: bounds width V: 0.
  144.     gPort movePenToX: (p x + 94 + 72) Y: (p y); drawLineByH: 0 V: -17.
  145.     gPort movePenToX: (p x + 94 + 72 + 120) Y: (p y); drawLineByH: 0 V: -17.
  146.     gPort movePenToX: (p x + 94 + 72 + 240) Y: (p y); drawLineByH: 0 V: -17.
  147.     p y: p y + 2.
  148.     gPort movePenTo: p; drawLineByH: bounds width V: 0.
  149.     
  150.     "Set the foreground color back to black"    
  151.     Color black setForeground.
  152.     
  153.     "Make a copy of the bounds (remember bounds some bounds methods are destructive) and frame a
  154.      rectangle that will contain the legal wire points"
  155.     bc := bounds copy.
  156.     
  157.     (Rectangle top: bc top + 34 left: bc left + 14 bottom: bc bottom -14 right: bc right - 14 ) frame.
  158.    
  159.     "Now draw our wires and points!!"
  160.     self drawWindowContents
  161.   
  162.     ' styleRuns:((ScrapStyle basicNew: 0) storageSize: 262; storageFromHexString: '000D00000000000B00090004000000090000000000000000004C000B0009000400000009999966660000000000AC000B000900040000000900000000000000000156000B00090004000000099999666600000000017D000B0009000400000009000000000000000001F2000B000900040000000999996666000000000234000B0009000400000009000000000000000003CB000B0009000400000009999966660000000003F4000B000900040000000900000000000000000420000B0009000400000009999966660000000004B4000B000900040000000900000000000000000540000B000900040000000999996666000000000560000B0009000400000009000000000000'))!
  163. (DemoLib@#WireListWindow methodAt: #'privateSelfRender:in:color:depth:') protocolCategory: #'update'.!
  164. (DemoLib@#WireListWindow methodAt: #'privateSelfRender:in:color:depth:') description: ('Called on every update by superclass (UIWindow) methods. THIS METHOD MUST BE DEFINED FOR YOUR APPLICATION WINDOW, OTHERWISE YOU WILL GET A DEFAULT WINDOW.').!
  165.  
  166. DemoLib@#WireListWindow compileMethodSource: (
  167. Text from: 'shorten
  168.  
  169.  
  170.     "Call the algorithms in WireList class to compute the new length"
  171.     module wires shorten.
  172.     
  173.     "info is an instance variable of WIreListWindow; it is assigned as a StaticTextField in the 
  174.      createWindow method. Here we update the string to be put in that StaticTextField. This may
  175.      appear to be a duplication of action by #buttonDown, but this is needed because we have to
  176.      update this message when we both add points and shorten wires"
  177.     info contents:  (''Length of wire is: '',((module wires length) printFormatted: ''%12.4f''),''.'').
  178.    
  179.     "Now mark the view dirty so the new wires can be drawn"
  180.       self markAsDirty.
  181. ' styleRuns:((ScrapStyle basicNew: 0) storageSize: 142; storageFromHexString: '000700000000000B00090004000000090000000000000000000E000B00090004000000099999666600000000004F000B000900040000000900000000000000000072000B0009000400000009999966660000000001D3000B00090004000000090000000000000000023E000B000900040000000999996666000000000275000B0009000400000009000000000000'))!
  182. (DemoLib@#WireListWindow methodAt: #'shorten') protocolCategory: #'event actions'.!
  183. (DemoLib@#WireListWindow methodAt: #'shorten') description: ('Called when you press the [shorten wire] button. This calls the algorithmic methods that compute the new (reduced) wire length. These algorithms are in the WireList class').!
  184.  
  185. DemoLib@#WireListWindow compileMethodSource: (
  186. Text from: 'updateInfo: length
  187.  
  188.     info contents:  (''Length of wire is: '',(length printFormatted: ''%12.4f''),''.'').
  189.     info markAsDirty.
  190. ' styleRuns:((ScrapStyle basicNew: 0) storageSize: 22; storageFromHexString: '000100000000000B0009000400000009000000000000'))!
  191.  
  192. DemoLib@#WireListWindow compileMethodSource: (
  193. Text from: 'drawWindowContents
  194.    
  195.    “Called this from privateSelfRender::: It calls the method that actually draws the 
  196.         wires based on the contents of the WireList.”
  197.     
  198.     
  199.     | wPort  |
  200.      wPort := self windowPort.
  201.      
  202.     module wires drawOn: wPort.
  203.     ' styleRuns:((ScrapStyle basicNew: 0) storageSize: 102; storageFromHexString: '000500000000000B00090004000000090000000000000000001A000B000900040000000999996666000000000041000C000A000100000009999966660000000000A2000B0009000400000009999966660000000000A3000B0009000400000009000000000000'))!
  204. (DemoLib@#WireListWindow methodAt: #'drawWindowContents') protocolCategory: #'update'.!
  205. (DemoLib@#WireListWindow methodAt: #'drawWindowContents') description: ('Called this from privateSelfRender::: It calls the method that actually draws the wires based on the contents of the WireList.').!
  206.  
  207. DemoLib@#WireListWindow compileMethodSource: (
  208. Text from: ' buttonDown
  209.  
  210.     "This method will control adding and moving of points in the display and updating of the
  211.      WireList"
  212.      
  213.     | p p2 indx dist tmp w pBnds |
  214.     
  215.    "Set up a copy of the bounds; a safe thing to do because many bounds methods are destructive"
  216.      pBnds := self windowPort bounds.
  217.    
  218.      "This is the point where you pressed the button"
  219.     p := Mouse localPosition.
  220.     
  221.     "We will restrict the region where we can add points to inside a Rectangle (black frame)"
  222.      ((Rectangle top: pBnds top + 34 left: pBnds left + 14 bottom: pBnds bottom -14 
  223.          right: pBnds right - 14 ) containsPoint: p) ifTrue: [
  224.    
  225.      w := module wires. "This is a temporary of the WireList"
  226.     
  227.     indx := 0.
  228.     dist := 5. "Magic number here is just the diameter of circle we draw at selected points"
  229.  
  230.    "For each entry in the WireList, measure its distance to p. If any point is closer than 5 to p
  231.     consider p and that point to be the same." 
  232.     1 to: (w size) do: [ :i |
  233.         tmp := w distance: i to: p.
  234.         (tmp < dist)
  235.             ifTrue: [ dist := tmp.  indx := i ].
  236.         ].
  237.     
  238.     "Otherwise, add the point to the list and update the current length message, draw the new point
  239.       and connect it to the either the last one drawn, or change its location"
  240.     (indx > 0)
  241.         ifFalse: [
  242.             module add: p.
  243.             self updateInfo: (w length).
  244.             self markAsDirty. "Mark the window so that we can update the drawing in it."
  245.             ^nil
  246.         ].
  247.         
  248.     w drawRubberBandWith: indx on: (self windowPort). "Either draw a new section or rubber band
  249.                                                         to a new position"
  250.    
  251.     ]
  252.     ifFalse: [Speakers beep]. "Tried to place a point outside the frame!!"
  253.     
  254.     
  255.    p2 := Mouse localPosition. "This is the position resulting from dragging the mouse during rubber 
  256.               banding"
  257.     
  258.     ((Rectangle top: pBnds top + 34 left: pBnds left + 14 bottom: pBnds bottom -14 
  259.    
  260.    right: pBnds right - 14 ) containsPoint: p2) ifTrue: [  "is it in the frame?"
  261.     
  262.     w at: indx put: p2. "Change the point location value at that index in the list"
  263.     
  264.     self updateInfo: (w length). "update the length message in the window"
  265.     
  266.     self markAsDirty. "Make sure we can draw in the relocated point and connect it"
  267.     ]
  268.     ifFalse: [Speakers beep]. "Tried to move it outside the frame"
  269.     
  270.     
  271.     "NOTES: We purposely do not erase the rubber band lines if you try to go outside the frame.
  272.             This way the user can see where he/she came from and either add a new point or
  273.             recover the prior position.
  274.             The drawRubberBand method draws the temporary relocation picture, but the 
  275.             drawWindowContents method updates the view"' styleRuns:((ScrapStyle basicNew: 0) storageSize: 682; storageFromHexString: '002200000000000B000900040000000900000000000000000011000B00090004000000099999666600000000007E000B0009000400000009000000000000000000AA000B000900040000000999996666000000000107000B000900040000000900000000000000000137000B000900040000000999996666000000000167000B00090004000000090000000000000000018F000B0009000400000009999966660000000001E8000B000900040000000900000000000000000299000B0009000400000009999966660000000002BE000B0009000400000009000000000000000002E2000B00090004000000099999666600000000032F000B000900040000000900000000000000000334000B0009000400000009999966660000000003C1000B00090004000000090000000000000000045F000B00090004000000099999666600000000050D000B000900040000000900000000000000000592000B0009000400000009999966660000000005CC000B000900040000000900000000000000000628000B00090004000000099999666600000000069C000B0009000400000009000000000000000006C5000B0009000400000009999966660000000006F0000B000900040000000900000000000000000719000B000900040000000999996666000000000776000B00090004000000090000000000000000080F000B000900040000000999996666000000000824000B000900040000000900000000000000000842000B00090004000000099999666600000000087D000B0009000400000009000000000000000008A4000B0009000400000009999966660000000008CD000B0009000400000009000000000000000008E9000B000900040000000999996666000000000926000B00090004000000090000000000000000094B000B0009000400000009999966660000'))!
  276. (DemoLib@#WireListWindow methodAt: #'buttonDown') protocolCategory: #'event actions'.!
  277. (DemoLib@#WireListWindow methodAt: #'buttonDown') description: ('Determines the actions to be taken when the user presses the mouse button in the main pane area (area exclusive of special components).').!
  278.  
  279. DemoLib@#WireListWindow compileMethodSource: (
  280. Text from: 'commandTyped
  281.  
  282.     "Takes string (str) from the text input field (TEField) and evaluates it. Useful for learning
  283.     and debugging. Try typing in [inspect] or [modules inspect]"
  284.  
  285.     | str |
  286.     
  287.     str := activeTarget contents.
  288.     
  289.     (str notNil)    ifTrue: [
  290.            Smalltalk evaluate: ''('',(self asWeakOOP asString),
  291.             ''asOOPFromWeakOOP )'', str.
  292.             
  293.             "self perform: str asSymbol <------ simpler form IF str is a selector"
  294.         ]
  295.     ' styleRuns:((ScrapStyle basicNew: 0) storageSize: 62; storageFromHexString: '000300000000000B000900040000000900000000000000000012000B0009000400000009999966660000000000B0000B0009000400000009000000000000'))!
  296. (DemoLib@#WireListWindow methodAt: #'commandTyped') protocolCategory: #'component msg'.!
  297. (DemoLib@#WireListWindow methodAt: #'commandTyped') description: ('Evaluation of string input from the TEField.').!
  298.  
  299. DemoLib@#WireListWindow compileMethodSource: (
  300. Text from: 'inspectWire
  301.  
  302.  
  303.         "Called when you press the <inspect wires> button"
  304.  
  305.         module wires inspect
  306.  
  307.     ' styleRuns:((ScrapStyle basicNew: 0) storageSize: 62; storageFromHexString: '000300000000000B000900040000000900000000000000000016000B000900040000000999996666000000000048000B0009000400000009000000000000'))!
  308. (DemoLib@#WireListWindow methodAt: #'inspectWire') protocolCategory: #'event actions'.!
  309. (DemoLib@#WireListWindow methodAt: #'inspectWire') description: ('Allows user to inspect the WireList.').!
  310.  
  311.